package simpledb.server.drivers;

import simpledb.file.Block;
import simpledb.server.SimpleDB;
import simpledb.tx.Transaction;

public class QCTestDriver {
	
	final static String fileName = "testdbdir.tbl";
    static Transaction initializer;
    static int blockOffset = 4;
    
    /*
     * The 3 different types of transactions.
     */
     static final int COMMIT = 1, ROLLBACK = 2, UNDO = 3;

	public static void main(String[] args) {


        SimpleDB.init("dbdir");
        initializer = new Transaction();
        Block[] blocks = new Block[6];
        // Initializing blocks.
        for (int i = 0; i < 6; i++) {
            blocks[i] = new Block(fileName, i);
            initializer.pin(blocks[i]);
            initializer.setInt(blocks[i], blockOffset, 111 * (i + 1));
        }
        initializer.commit();


        Thread[] threads = new Thread[6];

        threads[0] = new TestThread(0, 1, 100, 200, COMMIT);
        threads[1] = new TestThread(2, 3, 300, 400, COMMIT);
        threads[2] = new TestThread(4, 5, 500, 600, ROLLBACK);
        threads[3] = new TestThread(0, 1, 700, 800, COMMIT);
        threads[4] = new TestThread(2, 3, 900, 1000, UNDO);
        threads[5] = new TestThread(4, 5, 1100, 1200, UNDO);
		/*threads[0] = new TestThreadSingle(0, 1, 100, 200, COMMIT);
		threads[1] = new TestThreadSingle(1, 2, 300, 400, COMMIT);
		threads[2] = new TestThreadSingle(2, 3, 500, 600, ROLLBACK);
		threads[3] = new TestThreadSingle(3, 4, 700, 800, UNDO);
		threads[4] = new TestThreadSingle(4, 5, 900, 1000, COMMIT);
		threads[5] = new TestThreadSingle(5, 0, 1100, 1200, UNDO);*/
        try {
	        threads[0].start();threads[0].join();
	        threads[1].start();threads[1].join();
	        threads[2].start();threads[2].join();
        }
        catch (InterruptedException e) {
        	e.printStackTrace();
        }
        threads[3].start();
        threads[4].start();
        threads[5].start();
        
        try {
        	threads[3].join();
        	threads[4].join();
        	threads[5].join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("Ending Main ... ");

        //doRecovery1();
    }

}


class TestThread extends Thread { // Creates one transaction per thread.
    private int[] blockNums;
    private int[] values;
    private int transType;

    public TestThread(int block1, int block2, int value1, int value2, int type) {
        blockNums = new int[2];
        values = new int[2];
        blockNums[0] = block1;
        blockNums[1] = block2;
        values[0] = value1;
        values[1] = value2;
        transType = type;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        Transaction tx = new Transaction();
        Block blk1 = new Block(QChkptTestDriver.fileName, blockNums[0]);
        Block blk2 = new Block(QChkptTestDriver.fileName, blockNums[1]);

        tx.pin(blk1);
        tx.pin(blk2);

        //Updating the two blocks.
        tx.setInt(blk1, QChkptTestDriver.blockOffset, values[0]);
        tx.setInt(blk2, QChkptTestDriver.blockOffset, values[1]);
        String line = "#######################################################################";
        String status = line;
        status += "\nTransaction#: " + tx.getTxnum() + " writing " + values[0] + " to: " + blk1;
        status += "\nTransaction#: " + tx.getTxnum() + " writing " + values[1] + " to: " + blk2;
        status += "\nTransaction#: " + tx.getTxnum() + " will be ";

        switch (transType) {
            case QChkptTestDriver.COMMIT:
                tx.commit();
                status += "committed.";
                break;
            case QChkptTestDriver.ROLLBACK:
                tx.rollback();
                status += "rolled back.";
                break;

            case QChkptTestDriver.UNDO:
                //tx.undo();
                status += "undone.";
                break;

            default:
                break;
        }
        status += "\n" + line;
        //Print status of this transaction.
        System.out.println(status);
    }
}
